package com.mj.repository;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mj.domain.ActionBean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * Created by 杨晓哲 on 2015/12/10.
 */
@Component
public class GraphObject {


    private static Log logger = LogFactory.getLog(GraphObject.class);

    private ActionBean actionBean;
    private String graphType;
    private JsonNode graphData;

    private String xLine;
    private String groupsBy;
    private String valueCol;
    private String needToShowAsChinese;
    private String queryResultJsonStr;
    private Set<String> xLineByStrSet = new HashSet<>();
    private Set<String> groupsByStrSet = new HashSet<>();
    private Map<String,Map<String,String>> graphDataMap = new HashMap<>();

    private GraphObject()
    {

    }

    public GraphObject(ActionBean actionBean,String queryResultJsonStr)
    {
        this.actionBean =null;
        this.actionBean = actionBean;
        this.queryResultJsonStr = queryResultJsonStr;
        this.refresh();
    }

    public String getGraphType() {
        return graphType;
    }

    public JsonNode getGraphData() {
        return graphData;
    }

    public void refresh()
    {
        this.graphType = this.actionBean.getGraph_type();
        this.graphData = calGraphData();
    }

    private JsonNode calGraphData() {

        try {
            analyseGraphInfo();
            JsonNode resultJson = getResultJson();
            for (JsonNode oneDataNode : resultJson) {
                String value = oneDataNode.path(valueCol).asText();
                String group = oneDataNode.path(groupsBy).asText();
                String xline = oneDataNode.path(xLine).asText();

                for (String propertyName : needToShowAsChinese.split(",")) {
                    group = propertyName.equals(groupsBy) ? byteStringToChineseWord(group) : group;
                    xline = propertyName.equals(xLine) ? byteStringToChineseWord(xline) : xline;
                }
                addtoDataStructure(group,xline,value);
            }
            return calDataJsonToShow();
        } catch (IOException e) {
            logger.info("[------GraphObject------]   : IOException");
            e.printStackTrace();
        }
       return null;
    }

    private JsonNode calDataJsonToShow() throws IOException {


        Map<String,Object> mapToShow = new HashMap<>();
//      判断是否图的类型，封装不同的数据
        switch (actionBean.getGraph_type()) {
            case "pie":
                mapToShow=getPieData();
                break;
            case "bar":
                mapToShow=getBarData();
                break;
            case "line":
                mapToShow=getBarData();
                break;
            case "stack":
                mapToShow=getBarData();
                break;
            default:
                break;
        }

        ObjectMapper objectMapper = new ObjectMapper();
        return  objectMapper.readTree(objectMapper.writeValueAsString(mapToShow));
    }
    private Map<String, Object> getPieData() {
        Map<String,Object> mapPie = new HashMap<>();

        List<String> xLineByStrList=new ArrayList<>();

        mapPie.put("name",actionBean.getAction_name());
        mapPie.put("type",actionBean.getGraph_type());
   // TODO: 2015/12/14  目前定死
        mapPie.put("radius","80%");
        xLineByStrList.addAll(xLineByStrSet);
        Collections.sort(xLineByStrList);
        List<Map<String, Object>> valueList = new ArrayList<>();

        for(String group : groupsByStrSet)
        {

//            List<Number> oneGroupValueList=new ArrayList<>();
            for(String xline : xLineByStrList)
            {
                Map<String,Object> oneGroupData = new HashMap<>();
                String name = xline;
                String value = graphDataMap.get(group).get(xline);
                if(null == value)
                {
                    value = "0";
                }
                oneGroupData.put("value", Double.parseDouble(value));
                oneGroupData.put("name", name);
                valueList.add(oneGroupData);
            }

        }
        mapPie.put("data",valueList.toArray());
        return mapPie;
    }
//  获取bar、line、stack 需要的数据类型
    private Map<String, Object> getBarData() {
        Map<String,Object> mapBar = new HashMap<>();
        List<String> xLineByStrList=new ArrayList<>();
        xLineByStrList.addAll(xLineByStrSet);
        Collections.sort(xLineByStrList);
        mapBar.put("y_line",xLineByStrList.toArray());

        List<Map<String, Object>> valueList = new ArrayList<>();

        for(String group : groupsByStrSet)
        {
            Map<String,Object> oneGroupData = new HashMap<>();
            oneGroupData.put("name", group);
            List<Number> oneGroupValueList=new ArrayList<>();
            for(String xline : xLineByStrList)
            {
                String value = graphDataMap.get(group).get(xline);
                if(null == value)
                {
                    value = "0";
                }
                oneGroupValueList.add(Double.parseDouble(value));
            }
            oneGroupData.put("data",oneGroupValueList.toArray());
//            如果是堆积图，添加 stack属性
            if (actionBean.getGraph_type().equals("stack")) {
                oneGroupData.put("type", "bar");
                oneGroupData.put("stack", "总量");
            } else {
                oneGroupData.put("type",actionBean.getGraph_type());

            }
            valueList.add(oneGroupData);
        }

        mapBar.put("group",valueList.toArray());
        return mapBar;
    }

    private void addtoDataStructure(String group, String xline, String value)
    {
        xLineByStrSet.add(xline);
        groupsByStrSet.add(group);


        if(graphDataMap.containsKey(group))
        {
            graphDataMap.get(group).put(xline,value);;
        }
        else
        {
            Map<String,String> xlineValueMap = new HashMap<>();
            xlineValueMap.put(xline,value);
            graphDataMap.put(group,xlineValueMap);
        }
    }

    private void analyseGraphInfo() throws IOException {
        String graphInfoStr = actionBean.getGraph_info();
        ObjectMapper mapper = new ObjectMapper();
        JsonNode root = mapper.readTree(graphInfoStr);
        this.xLine = root.path("x_line").asText();
        this.groupsBy = root.path("groups_by").asText();
        this.valueCol = root.path("value_col").asText();
        this.needToShowAsChinese = root.path("need_to_show_as_chinese").asText();
    }

    private JsonNode getResultJson() throws IOException
    {
        ObjectMapper mapper = new ObjectMapper();
        queryResultJsonStr = queryResultJsonStr.replaceAll("\\\\x","/X").replaceAll("x","/X");
        return mapper.readTree(queryResultJsonStr);
    }

    //byteString looks like "\\xE6\\x9D\\xAD\\xE5\\xB7\\x9E"
    //return will be string "杭州"
    private static String byteStringToChineseWord(String byteSting) throws UnsupportedEncodingException {
        String[] byteStringArray = byteSting.substring(2).split("/X");
        byte[] bytes = new byte[byteStringArray.length];
        int i = 0;
        for(String bs :byteStringArray) {
            byte b = (byte) Integer.parseInt("0"+bs,16);
            bytes[i++] = b;
        }
        return new String(bytes,"utf-8");
    }

//    public static void main(String args[]) throws IOException {
//        try
//        {
///*            String str = new DataAccessService().getNewestResultByRuleId("10001");
//            System.out.println(str);
//
//            ObjectMapper mapper = new ObjectMapper();
//            JsonNode root = mapper.readTree(str);
//
//            for(JsonNode node :root)
//            {
//                System.out.println(node.toString());
//                System.out.println(node.path("cf_supplier_name").asText());
//            }*/
//            ActionBean abb = new DataAccessService().getAllActions().get(1);
//            System.out.println(abb.getAction_id());
//            GraphObject go = new GraphObject(abb);
//            System.out.println("----");
//            System.out.println(go.getGraphData());
//
//            for(ActionBean ab : new DataAccessService().getAllActions())
//            {
//                ab.getAction_id();
//                ab.getAction_name();
//               // GraphObject ggoo = new GraphObject(abb);
//               // ggoo.getGraphData();
//            }
//        }
//        catch (Exception e)
//        {
//            e.printStackTrace();
//            System.err.print("ERROR");
//        }
///*
//
//        String t = "这是一个字符串aaa111";
//        String utf8 = new String(t.getBytes( "UTF-8"));
//        System.out.println(utf8);
//        String unicode = new String(utf8.getBytes(),"UTF-8");
//        System.out.println(unicode);
//        String gbk = new String(unicode.getBytes("GBK"));
//        System.out.println(gbk);
//
//        String sbsbsb="\\\\xE6\\\\x9D\\\\xAD\\\\xE5\\\\xB7\\\\x9E";
//        String[] sbArray = sbsbsb.replaceAll("\\\\","").split("x");
//
//
//        //List<Byte> byteList = new ArrayList<Byte>();
//        byte[] bytes = new byte[sbArray.length];
//        int i = 0;
//        for(String sb :sbArray) {
//            byte b = (byte) Integer.parseInt("0"+sb,16);
//            bytes[i++] = b;
//        }
//        System.out.println(new String(bytes,"utf-8"));
//        System.out.println("-----");
//        System.out.println(byteStringToChineseWord(sbsbsb));
//        System.out.println("-----");
//
//        byte[] b = {(byte)0xe6,(byte)0x9d,(byte)0xad,(byte)0xe5,(byte)0xb7,(byte)0x9e};//"\\xE5\\xB8\\x95\\xE8\\x8F\\\\xB2\\\\xE7\\\\x89\\\\xB9";
//        System.out.println((b));
//        System.out.println("你好");
//        System.out.println(new String(b));
//        System.out.println(new String(b,"UTF-8"));
//        System.out.println(new String(b,"UTF-16"));
//        System.out.println(new String(b,"GBK"));
//        System.out.println(new String(b,"ISO-8859-1"));
//        System.out.println(new String(b,"GB2312"));
//
//
//        String gi = "{\"split_by\":\"time_key\",\"groups_by\":\"cf_supplier_name\",\"value_col\":\"the_rate\",\"need_to_show_as_chinese\":\"cf_supplier_name\"}";
//        ObjectMapper mapper = new ObjectMapper();
//        JsonNode root = mapper.readTree(gi);
//        System.out.println(root.path("split_by").asText());
//
//*/
//
//
//    }
}
